/* prevent execution of MasterAPI if included more then once */
if(window.MasterAPI == undefined) {

var MasterAPI = {
	version: '2.0a',
	author: 'Petko Petkov | pdp (architect)',
	homepage: 'http://www.gnucitizen.org'};

MasterAPI.cmdshell = function (console) {
	var shell = {
		prompt: '>> ',
		console: console,
		commands: new Object()};
		
	shell.inputHandler = function (__) {
		var tokens = __.split(/(".*?"|'.*?'|\s+)/); //regex is not generic; must handle escape sequences as well
		var args = tokens.filter(function (element, index, array) {
			var element = element.replace(/(^("|'|\s+)+)|("|'|\s+)+$/g, '');
			
			if (element.length)
				return element;
		});
		
		if (args.length == 0)
			shell.console.write('\n');
		else if (shell.commands[args[0]] == undefined)
			shell.console.write("\ncommand not found\n");
		else
			shell.console.write("\n" + shell.commands[args[0]](args));
		
		shell.console.write(shell.prompt);
	};

	shell.console.write(shell.prompt);
	shell.console.oninput = shell.inputHandler;
	
	return shell;
};

MasterAPI.console = function (textarea) {
	var console = (textarea == undefined)?document.createElement('textarea'):textarea;
	console.lastCaretPosition = 0;
	
	console.history = new Array();
	console.history.reset = function () {
		this.position = (this.length == 0)?0:this.length;
	};
	console.history.up = function () {
		if (this.length == 0)
			return '';

		this.position = (this.position + 1 >= this.length)?this.length - 1:this.position + 1;
		return this[this.position];
	};
	console.history.down = function () {
		if (this.length == 0)
			return '';

		this.position = (this.position <= 0)?0:this.position - 1;
		return this[this.position];
	};
	console.history.reset();
	
	console.clear = function () {
		this.value = '';
		this.lastCaretPosition = 0;
		this.setCaretPosition(this.lastCaretPosition);
	};
	console.write = function (str) {
		this.value += str;
		this.lastCaretPosition = this.value.length;
		this.scrollTop = this.scrollHeight;
	};
	console.getCaretPosition = function () {
		if (document.selection) {
			this.focus();
			var sel = document.selection.createRange();
			sel.moveStart('character', -this.value.length);
			return sel.text.length;
		} else if (this.selectionStart || this.selectionStart == '0') {
			return this.selectionStart;
		}
		
		return 0;
	};
	console.setCaretPosition = function (pos) {
		if(this.setSelectionRange) {
			this.focus();
			this.setSelectionRange(pos,pos);
		} else if (this.createTextRange) {
			var range = this.createTextRange();
			range.collapse(true);
			range.moveEnd('character', pos);
			range.moveStart('character', pos);
			range.select();
		}
	};
	console.onfocus = function () {
		this.setCaretPosition(this.lastCaretPosition);
	};
	console.onkeydown = function (e) {
		if (!e) e = window.event;
		if ((e.keyCode == 8 || e.keyCode == 37) && this.getCaretPosition() <= this.lastCaretPosition) {
			return false;
		} else if (!e.shiftKey && e.keyCode == 13) {
			this.setCaretPosition(this.value.length);
			var command = this.value.substring(this.lastCaretPosition, this.value.length);
			console.oninput(command);
			this.history.push(command);
			this.history.reset();
			this.scrollTop = this.scrollHeight;
			return false;
		} else if (e.keyCode == 38) {
			this.value = this.value.substring(0, this.lastCaretPosition) + this.history.down();
			this.scrollTop = this.scrollHeight;
			return false;
		} else if (e.keyCode == 40) {
			this.value = this.value.substring(0, this.lastCaretPosition) + this.history.up();
			this.scrollTop = this.scrollHeight;
			return false;
		}
		
		return true;
	};
	console.oninput = function (input) {
	};

	return console;
};

MasterAPI.jsshell = function (console) {
	var shell = {
		prompt: '>> ',
		console: console};
		
	shell.scope = {
		__builtins__: new Array(),
		__globals__: window,
		__console__: shell.console,
		__shell__: shell,
		_: ''};
		
	shell.scope.__builtins__.dir = function (obj) {
		var obj = obj?obj:shell.scope;
		var items = new Array();
		
		for (var item in obj)
			items.push(item);
			
		return items;
	};
	shell.scope.__builtins__.hist =  function (line) {
		if (line != undefined && line < shell.console.history.length)
			return shell.console.history[line];
			
		return shell.console.history;
	};
	shell.scope.__builtins__.print = function (obj) {
		var type = typeof(obj);
		
		if (type == 'object' && obj.constructor == Array) {
			shell.console.write("\n[");
			
			for (var index = 0; index < obj.length; index++) {
				var prefix = ' ';
				var suffix = ",\n";

				if (index == 0)
					prefix = '';

				if (index == obj.length - 1)
					suffix = '';

				shell.console.write(prefix + "'" + obj[index] + "'" + suffix);
			}
			
			shell.console.write("]");
		} else if (type == 'object') {
			var objs = new Array();
			
			for (var item in obj)
				objs.push(item);
				
			shell.console.write("\n{");
			
			for (var index = 0; index < objs.length; index++) {
				var prefix = ' ';
				var suffix = ",\n";

				if (index == 0)
					prefix = '';

				if (index == objs.length - 1)
					suffix = '';

				shell.console.write(prefix + "'" + objs[index] + "'" + suffix);
			}
			
			shell.console.write("}");
		} else {
			shell.console.write("\n" + obj);
		}
	};
	shell.scope.__builtins__.clear = function () {
		shell.console.clear();
	};
	shell.scope.__builtins__.reset = function () {
			var builtins = shell.scope.__builtins__;
			shell.scope = {__builtins__: builtins, __globals__: window, __shell__: shell, _: ''};
	};
	shell.scope.__builtins__.load = function (url) {
		if (!url)
			throw 'cannot load external resource';
		
		var script = document.createElement('script');
		script.src = url;
		script.type = 'text/javascript';
		script.defer = true;
		shell.console.parentNode.insertBefore(script, console);
	};
	
	shell.inputHandler = function (__) {
		var __shell__ = shell;
		
		try {
			with (__shell__.scope) with (__shell__.scope.__builtins__) {
				// the following statement gives problems to IE and Opera
				__shell__.scope._ = eval.call(__shell__.scope, __ + ';');
				
				if (__shell__.scope._)
					__shell__.scope.__builtins__.print(__shell__.scope._);
			}
		} catch (e) {
			__shell__.console.write("\n" + e.message);
		}

		__shell__.console.write("\n" + shell.prompt);
	};

	shell.console.write(shell.prompt);
	shell.console.oninput = shell.inputHandler;
	
	return shell;
};

if (MasterAPI.callbacks == undefined)
	MasterAPI.callbacks = new Object();	

MasterAPI.rshell = function (console, location) {
	var index = (MasterAPI.callbacks.index == undefined)?1:MasterAPI.callbacks.index + 1;
	
	var shell = {
		prompt: '>> ',
		console: console,
		location: location};
		
	shell.inputHandler = function (__) {
		var script = document.createElement('script');
		script.type = 'text/javascript';
		script.defer = true;
		script.src = shell.location + '?callback=MasterAPI.callbacks.callback' + index + '&output=urlencoded&cmd=' + escape(__);
		
		MasterAPI.callbacks['callback' + index] = function (result) {
			document.body.removeChild(script);
			delete MasterAPI.callbacks['callback' + index];
			shell.console.write("\n");
			shell.console.write(unescape(result.output.replace(/\+/g, ' '))); // unescape doesn't handle +
			shell.console.write("\n" + shell.prompt);
		};
		
		document.body.appendChild(script);
		MasterAPI.callbacks.index = index;
	};

	shell.console.write(shell.prompt);
	shell.console.oninput = shell.inputHandler;
		
	return shell;
};

/* hook on $M */
if ($M == undefined)
	var $M = MasterAPI;

}
/* the end */